/**********************************************************************/
/*                                                                    */
/*      File bwa.c:  Multiprocessor System Bandwidth Computation      */
/*                                                                    */
/*  This program comprises a simple "main()" program together with    */
/*  the bandwidth computation functions of Figure 5.3.  It computes   */
/*  the bus bandwidth for a system with N processors, M memories,     */
/*  and B buses using the model developed in Section 5.3.             */
/*                                                                    */
/**********************************************************************/
#include <stdio.h>
#include <math.h>

typedef double real;
#define then

main()
  {
    int B,M,N; real p,bw,BW(); char s[32];
    while (1)
      {
        printf("\nenter B  M  N  p: ");
        gets(s);  if (s[0]=='\0') then exit(0);
        sscanf(s,"%d %d %d %lf",&B,&M,&N,&p);
        printf("bw = %.3f\n",BW(p,B,M,N));
      }
  }

real BW(p,B,M,N)
  real p; int B,M,N;
    {
      real bw0,bw1=p*N,r=p,x=1.0/p-1.0,BWi();
      do
        {
          bw0=bw1; r=1.0/(1.0+x*bw0/(N*r));
          bw1=BWi(r,B,M,N);
        }
      while (fabs(bw1-bw0)>0.005);
      return(bw1);
    }

real BWi(r,B,M,N)
  real r; int B,M,N;
    { /* compute bandwith for request rate r */
      int i; real q,bw=0.0,f();
      q=1.0-pow(1.0-r/M,(real)N);
      for (i=1; i<B; i++)  bw+=i*f(i,M,q);
      for (i=B; i<=M; i++) bw+=B*f(i,M,q);
      return(bw);
    }

real Fact(n)
  int n;
    { /* compute n factorial */
      real z=1.0;
      while (n) {z*=n; n--;}
      return(z);
    }

real C(n,k)
  int n,k;
    { /* compute binomial coefficient */
      return(Fact(n)/(Fact(k)*Fact(n-k)));
    }

real f(i,M,q)
  int i,M; real q;
    { /* compute binomial probability */
      real z;
      z=C(M,i)*pow(q,(real)i)*pow(1.0-q,(real)(M-i));
      return(z);
    }
